/*
* 	在没有标准的C函数库的支持下完成整数转换为整数的字符串形式。
* 	与C库相比，这没有达到标准C库中的完整功能！！
* 	这只支持int为2字节情况下的转换，若int为4字节则出现转换出现错误。
* 	把整数的字符串形式转换为整数。
* 	char *itoa(int val, char *buf, int ct);
* 	val为要转换的整数，buf为转换后的字符串缓冲区，为了避免溢出缓冲区长度应该大于6，
* 	ct为转换后以ct进制表示。现在只支持16，10,2进制表示。
* 	把整数转换为字符串形式
* 	int atoi(char *buf);
* 	buf为整数的字符串缓冲区，返回值为转换结果。
* 	atoi目前只支持10进制转换！！
*/
#include "convert.h"

static char code num_str[16] = {
	'0', '1', '2', '3', '4', '5', '6', '7',
	'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};

/* 计算表示为16进制要用多少个数字 */
static int hex_max_digit(unsigned int val)
{
	int ret = 0;
	/*
	*  	Demo:
	* 	18 / 16 = 2;
	* 	2 / 16 = 0;
	*  	需要两个数字
	 */
	while(val > 0) {
		val /= 16;
		++ret;
	}
	return ret;
}

/* 计算表示为2进制要用多少个数字 */
static int bin_max_digit(unsigned int val)
{
	int ret = 0;
	while(val > 0) {
		val /= 2;
		++ret;
	}
	return ret;
}

/* 计算表示为10进制要用多少个数字 */
static int dec_max_digit(int val)
{
	int ret = 0;
	while(val > 0) {
		val /= 10;
		++ret;
	}
	return ret;
}

char *itoa(int val, char *buf, int ct)
{
	char *p = buf;
	//int tmp;
	//int i;
	int max_dig;
	unsigned int uval;
	switch(ct) {
		case 2:
			uval = (unsigned int)val;
			if(uval == 0) {
				*buf++ = '0';
				*buf++ = 'b';
				*buf++ = '0';
				*buf++ = '0';
				*buf = '\0';
				goto ext;
 			}
			max_dig = bin_max_digit(uval);
			*buf++ = '0';
			*buf++ = 'b';
			buf[max_dig] = '\0';
			while(max_dig > 0) {
				buf[--max_dig] = num_str[uval % 2];
				uval /= 2;
			}
			break;
		case 8:

			break;
		case 10:
			if(val == 0) {
				*buf++ = '0';
				*buf = '\0';
				goto ext;
			}
        	if(val & 0x8000) {
        		val = ~val;
        		val += 1;
        		*buf = '-';
        		++buf;
        	}
			max_dig = dec_max_digit(val);
			buf[max_dig] = '\0';
			while(max_dig > 0) {
				buf[--max_dig] = num_str[val % 10];
				val /= 10;
			}
			break;
		case 16:
		    uval = (unsigned int)val;
		    if(uval == 0) {
		    	*buf++ = '0';
		    	*buf++ = 'x';
		    	*buf++ = '0';
		    	*buf++ = '0';
		    	*buf = '\0';
		    	goto ext;
		    }
		    max_dig = hex_max_digit(uval);
		    *buf++ = '0';
		    *buf++ = 'x';
		    buf[max_dig] = '\0';
		    while(max_dig > 0) {
		    	buf[--max_dig] = num_str[uval % 16];
		    	uval /= 16;
		    }
			break;
		default:
			*buf = '\0';
			break;
	}
ext:
	return p;
}

/* 判断字符串中是否全部为‘数字’ */
static int is_digital(char *buf)
{

	char *p = buf;
	while(*p != '\0') {
		if(*p < 48 || *p > 57)
			return 0;
		++p;
	}
	return 1;
}

/* strlen功能 */
static int cvstrlen(char *buf)
{
	int ret = 0;

	while(*buf != '\0') {
		++ret;
		++buf;
	}
	return ret;
}

/* 获取数字字符串形式最高位所在的位置 */
static char *trim_l(char *buf)
{
	while(*buf != '\0') {
		if(*buf == '0') {
			++buf;
		} else {
			break;
		}
	}
	return buf;
}

/* 字符串与数字之间的映射 */
static unsigned int chr_to_num(char *p)
{
	switch(*p) {
		case '0': return 0;
		case '1': return 1;
		case '2': return 2;
		case '3': return 3;
		case '4': return 4;
		case '5': return 5;
		case '6': return 6;
		case '7': return 7;
		case '8': return 8;
		case '9': return 9;
		default: return 0;
	}
}

/*
* 	Demo:
* 	12 = 1*10 + 2*1;
* 	121 = 1*100 + 2*10 + 1*1;
* 	1234 = 1*1000 + 2*100 + 3*10 + 4*1;
 */
static unsigned int multi_ten(unsigned int n, unsigned int m)
{
	while(m) {
		n = n*10;
		--m;
	}
	return n;
}

/* string to int顾名思义 */
static int str_to_int(char *p, int len)
{

	unsigned int ret = 0;
	int i, j;
	unsigned int elem[5];
	unsigned int tmp;
	/* 在C51中int为2字节最大表示65535不大于5位数字 */
	if(len > 5)
		return 0;
	/* memset功能 */
	for(i = 0; i < 5; i++)
		elem[i] = 0;
	tmp = 4;
	/*
	* 	Demo:
	* 	p = "1314";
	* 	依次分别取出独立的数字到数组中
	 */
	for(i = len-1; i >= 0; i--) {
		elem[tmp--] = chr_to_num(&p[i]);
	}
	/* 最大65535 */
	if(elem[0] > 6)
		return 0;
	j = 4;
	for(i = 0; i < 5; i++) {
		tmp = multi_ten(elem[i], j--);
		/* 排除大于65535的整数，因为一个int无法存储 */
		if((65535 - ret) < tmp) {
			return 0;
		}
		ret += tmp;
	}
	return ret;
}

int atoi(char *buf)
{
	int len;
	char *p = (char *)0;
	if(!is_digital(buf))
		return 0;
	p = trim_l(buf);
	len = cvstrlen(p);
	if(len == 0)
		return 0;
	return str_to_int(p, len);
}
